﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RacePlatformer;
using Microsoft.Xna.Framework;
using FarseerPhysics.Dynamics;
using RacePlatformer.Manager;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Factories;
using FarseerPhysics;
using Microsoft.Xna.Framework.Input;

namespace Dwarfs.Object.Boss
{
    public class Boss : GameObject
    {
        private Animation fallAnimation, talkanimation, spawnAnimation, talkBalloon,plofAnimation,talkBalloonF;
        private enum BossState { falling, landed, idle, talking, spawnPlayers,ploffing }
        private BossState currentState = BossState.falling;
        private Vector2 moveVector = Vector2.Zero;
        private int level;
        private TimeSpan startTalkTime;
        private TimeSpan talkTimeout = TimeSpan.FromSeconds(2f);
        private bool doneSpawningPlayers = false;
        public Boss(MainGame maingame, World world, Vector2 size, Vector2 position, BodyType bodytype, float mass, int levelID)
            : base(maingame, world, size, position, bodytype, mass, levelID)
        {
            this.body.OnCollision += BossColl;
        }
        public Boss(MainGame maingame, World world, Vector2 position, int ID, int levelID)
            : base(maingame, world, position, levelID)
        {
            this.body = BodyFactory.CreateRectangle(world, UnitsConverter.ToSimUnits(mainAnimation.frameWidth), UnitsConverter.ToSimUnits(mainAnimation.frameHeight), 1f, UnitsConverter.ToSimUnits(position));
            this.body.BodyType = BodyType.Dynamic;
            this.body.Mass = 50f;
            this.layer = 0.45f;
            this.scale = 1.0f;
            this.level = levelID;
            this.body.LinearDamping = 9f;
            this.body.OnCollision += BossColl;
        }
        private bool BossColl(Fixture fixtureA, Fixture fixtureB, Contact contact)
        {
            if (fixtureB.CollisionGroup != CollisionGroupManager.GROUND)
            {
                this.body.IgnoreCollisionWith(fixtureB.Body);
            }
            if (currentState == BossState.falling)
            {
                if (fixtureB.CollisionGroup == CollisionGroupManager.GROUND)
                {
                    //if collides with ground
                    this.body.LinearVelocity = Vector2.Zero;
                    this.moveVector = Vector2.Zero;
                    //play boss PLOF SOUND :D:D:D:D AND PLAY BOSS PLOF ANIMATION YES!

                    switchState("landed, so play plof", BossState.ploffing);
                }
            }
            return true;
        }
        public void launchBoss(Vector2 launchVector)
        {
            this.body.ApplyLinearImpulse(launchVector);
        }
        public void moveBoss(Vector2 moveVector)
        {
            this.moveVector = moveVector;
            this.body.LinearVelocity = moveVector;
        }
        public override void Update(GameTime gametime)
        {
            switch (currentState)
            {
                case BossState.falling:
                    if (moveVector != Vector2.Zero)
                    {
                        this.body.LinearVelocity = new Vector2(moveVector.X, this.body.LinearVelocity.Y);
                    }
                    break;
                case BossState.ploffing:
                    plofAnimation.update(gametime);
                    if (plofAnimation.animationFinished)
                    {
                        switchState("done with plof animation", BossState.landed);
                    }
                    break;
                case BossState.landed:
                    talkBalloonF.update(gametime);
                    if (Keyboard.GetState().IsKeyDown(Keys.F))
                    {
                        switchState("pressed 'F' ", BossState.spawnPlayers);
                    }
                    break;
                case BossState.idle: break;
                case BossState.spawnPlayers:
                    if (mainAnimation.currentFrame == (mainAnimation.amountofFrames / 2))
                    {
                        if (!doneSpawningPlayers)
                        {
                            maingame.createPlayers(level, maingame.goManager.amountofPlayersSpawning, new Vector2(UnitsConverter.ToDisplayUnits(this.body.Position.X), UnitsConverter.ToDisplayUnits(this.body.Position.Y - (UnitsConverter.ToSimUnits(mainAnimation.frameHeight / 2)))));
                            doneSpawningPlayers = true;
                        }
                    }
                    if (mainAnimation.animationFinished)
                    {
                        startTalkTime = gametime.TotalGameTime;
                        switchState("finished creating players", BossState.talking);
                    }
                    break;
                case BossState.talking:
                    talkBalloon.update(gametime);
                    if (gametime.TotalGameTime - startTalkTime > talkTimeout)
                    {
                        switchState("talk timeout done", BossState.idle);
                    }
                    break;
            }
            this.mainAnimation.update(gametime);
        }
        public override void Draw(GameTime gametime, Microsoft.Xna.Framework.Graphics.SpriteBatch batch)
        {
            switch (currentState)
            {
                case BossState.falling:
                    setAnimation(talkanimation);
                    break;
                case BossState.idle:

                    break;
                case BossState.ploffing:
                    setAnimation(talkanimation);
                    batch.Draw(plofAnimation.texture, new Vector2(UnitsConverter.ToDisplayUnits(this.body.Position.X), UnitsConverter.ToDisplayUnits(this.body.Position.Y) + 75), new Rectangle((int)(plofAnimation.currentFrame * plofAnimation.frameWidth), 0, (int)plofAnimation.frameWidth, (int)plofAnimation.frameHeight), Color.White, rotation, new Vector2((plofAnimation.frameWidth / 2), (plofAnimation.frameHeight / 2)), scale, desiredSpriteEffect, 0.4f);
                    //batch.Draw(plofAnimation.texture, new Vector2(UnitsConverter.ToDisplayUnits(this.body.Position.X)-20, UnitsConverter.ToDisplayUnits(this.body.Position.Y) + 75), new Rectangle((int)(plofAnimation.currentFrame * plofAnimation.frameWidth), 0, (int)plofAnimation.frameWidth, (int)plofAnimation.frameHeight), Color.White, rotation, new Vector2((plofAnimation.frameWidth / 2), (plofAnimation.frameHeight / 2)), scale, desiredSpriteEffect, 0.4f);
                    break;
                case BossState.landed:
                    batch.Draw(talkBalloonF.texture, new Vector2(UnitsConverter.ToDisplayUnits(this.body.Position.X) + 70, UnitsConverter.ToDisplayUnits(this.body.Position.Y) - 70), new Rectangle((int)(talkBalloonF.currentFrame * talkBalloonF.frameWidth), 0, (int)talkBalloonF.frameWidth, (int)talkBalloonF.frameHeight), Color.White, rotation, new Vector2((talkBalloonF.frameWidth / 2), (talkBalloonF.frameHeight / 2)), scale, desiredSpriteEffect, layer);
                    setAnimation(talkanimation);
                    break;
                case BossState.talking:
                    batch.Draw(talkBalloon.texture, new Vector2(UnitsConverter.ToDisplayUnits(this.body.Position.X) + 70, UnitsConverter.ToDisplayUnits(this.body.Position.Y) - 70), new Rectangle((int)(talkBalloon.currentFrame * talkBalloon.frameWidth), 0, (int)talkBalloon.frameWidth, (int)talkBalloon.frameHeight), Color.White, rotation, new Vector2((talkBalloon.frameWidth / 2), (talkBalloon.frameHeight / 2)), scale, desiredSpriteEffect, layer);
                    setAnimation(talkanimation);
                    break;
                case BossState.spawnPlayers:
                    setAnimation(spawnAnimation);
                    break;
                default: setAnimation(talkanimation);
                    break;
            }
            batch.Draw(mainAnimation.texture, UnitsConverter.ToDisplayUnits(this.body.Position), new Rectangle((int)(mainAnimation.currentFrame * mainAnimation.frameWidth), 0, (int)mainAnimation.frameWidth, (int)mainAnimation.frameHeight), Color.White, rotation, new Vector2((mainAnimation.frameWidth / 2), (mainAnimation.frameHeight / 2)), scale, desiredSpriteEffect, layer);
        }
        private void setAnimation(Animation newAnimation)
        {
            mainAnimation.animationFinished = false;
            mainAnimation = newAnimation;
        }
        private void switchState(String reason, BossState newState)
        {
            currentState = newState;
            Console.WriteLine("Switched state with reason : " + reason);
        }
        public override void LoadContent()
        {
            talkanimation = new Animation(maingame, "Objects/Boss/boss_talk_strip", 9, 144, 152, TimeSpan.FromSeconds(.02f), Animation.AnimationType.contious);
            talkBalloon = new Animation(maingame, "Objects/Boss/text_balloon_strip", 6, 100, 80, TimeSpan.FromSeconds(.02f), Animation.AnimationType.contious);
            talkBalloonF = new Animation(maingame, "Objects/Boss/text_balloonF_strip", 6, 100, 80, TimeSpan.FromSeconds(.02f), Animation.AnimationType.contious);
            spawnAnimation = new Animation(maingame, "Objects/Boss/boss_spawn_strip", 20, 142, 152, TimeSpan.FromSeconds(.05f), Animation.AnimationType.once);
            plofAnimation = new Animation(maingame, "Objects/Boss/boss_plof_strip", 10, 150, 60, TimeSpan.FromSeconds(.1f), Animation.AnimationType.once);
            this.mainAnimation = talkanimation;
        }
    }
}
